package com.ruoyi.hcrf.enums;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ConcurrentHashSet;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;

import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author wanglf
 */
public abstract class BaseCondition {
    private String orderByField;
    private static final String ORDER_BY_FIELD_SEPARATOR = ",";
    private static final String EMPTY = " ";
    protected static volatile ConcurrentHashSet<String> allowFilterField = null;

    protected Set<String> listAllowOrderByField() {
        Class<?> clazz = this.getClass();
        if (!AllowOrderFieldCache.containClass(clazz.getSimpleName())) {
            Class var2 = AllowOrderFieldCache.class;
            synchronized(AllowOrderFieldCache.class) {
                if (!AllowOrderFieldCache.containClass(clazz.getSimpleName())) {
                    Field[] fields = ReflectUtil.getFields(this.getClass());
                    Set<Field> allowOrderFieldSet = (Set) Arrays.stream(fields).filter((i) -> {
                        return 0 != ((AllowOrderField[])i.getAnnotationsByType(AllowOrderField.class)).length;
                    }).collect(Collectors.toSet());
                    Set<String> fieldSet = new HashSet<>(allowOrderFieldSet.size());

                    for (Field field : allowOrderFieldSet) {
                        AllowOrderField annotation = ((AllowOrderField[]) field.getAnnotationsByType(AllowOrderField.class))[0];
                        if (StrUtil.isNotBlank(annotation.value())) {
                            fieldSet.add(annotation.value());
                        } else {
                            fieldSet.add(StrUtil.toUnderlineCase(field.getName()));
                        }
                    }

                    AllowOrderFieldCache.setCacheOnClass(clazz, fieldSet);
                }
            }
        }

        return AllowOrderFieldCache.getFieldCacheByClass(clazz);
    }

    public List<OrderField> getOrderByFieldList() {
        Set<String> allowOrderByField = this.listAllowOrderByField();
        if (!CollectionUtil.isEmpty(allowOrderByField) && !StrUtil.isBlank(this.orderByField)) {
            List<String> targetOrderByFields = (List)Arrays.stream(this.orderByField.split(",")).map(String::trim).collect(Collectors.toList());
            List<OrderField> orderFieldList = new ArrayList<>();
            String field = null;
            String sort = null;
            String sqlErrorMessage = "使用了违规的排序字段";

            for(Iterator<String> var7 = targetOrderByFields.iterator(); var7.hasNext(); sort = null) {
                String orderField = var7.next();
                int lastIndexOfEmpty = orderField.lastIndexOf(" ");
                if (lastIndexOfEmpty > 0) {
                    field = orderField.substring(0, lastIndexOfEmpty).trim();
                    sort = orderField.substring(lastIndexOfEmpty).trim().toUpperCase();
                } else {
                    field = orderField.trim();
                }

                if (StrUtil.isBlank(sort)) {
                    sort = "ASC";
                } else if (!"ASC".equals(sort) && !"DESC".equals(sort)) {
                    throw new RuntimeException("使用了违规排序方式");
                }

                if (!allowOrderByField.contains(field)) {
                    throw new RuntimeException("使用了违规的排序字段");
                }

                orderFieldList.add(new OrderField(field, sort));
                field = null;
            }

            return orderFieldList;
        } else {
            return CollectionUtil.newArrayList(new OrderField[0]);
        }
    }

    public String concatOrderBy() {
        List<OrderField> orderFields = this.getOrderByFieldList();
        if (!CollectionUtil.isNotEmpty(orderFields)) {
            return "";
        } else {
            StringJoiner sj = new StringJoiner(",", " order by ", " ");

            for (OrderField orderField : orderFields) {
                sj.add(orderField.toString());
            }

            return sj.toString();
        }
    }

    public BaseCondition() {
    }

    public String getOrderByField() {
        return this.orderByField;
    }

    public void setOrderByField(final String orderByField) {
        this.orderByField = orderByField;
    }
}
